package com.hxh.area.service.impl;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hxh.area.entity.Area;
import com.hxh.area.mapper.AreaMapper;
import com.hxh.area.service.AreaService;
import com.hxh.area.vo.AreaVo;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Element;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * @author huangxunhui
 * Date: Created in 2021/8/14 22:55
 * Utils: IntelliJ IDEA
 */
@Service
public class AreaServiceImpl extends ServiceImpl<AreaMapper, Area> implements AreaService {

    // 爬取目标
    private static final String TARGET = "http://www.mca.gov.cn/article/sj/xzqh/2020/20201201.html";

    @Override
    public void parase() throws IOException {
        AtomicInteger province = new AtomicInteger();
        AtomicInteger city = new AtomicInteger();
        AtomicInteger parent = new AtomicInteger();

        // 请求网页
        List<Area> areaList = Jsoup.connect(TARGET).timeout(10000).get()
                // 筛选出 tr 标签
                .select("tr")
                // 筛选出 tr 下的 td 标签
                .stream().map(tr -> tr.select("td")
                        // 过滤 值为空的 td 标签，并转换为 td 列表
                        .stream().filter(td -> StringUtils.isNotBlank(td.text())).collect(Collectors.toList()))
                // 前面提到，区域码和区域名称分别存储在 第一和第二个td，所以过滤掉不符合规范的数据行。
                .filter(e -> e.size() == 2)
                // 转换为 area 对象
                .skip(1)
                .map(e -> {
                    String areaCode = e.get(0).text();
                    Element areaName = e.get(1);
                    if (areaName.childNodeSize() == 1) {
                        province.set(Integer.parseInt(areaCode));
                        parent.set(0);
                    } else if (areaName.child(0).wholeText().equals(" ")) {
                        city.set(Integer.parseInt(areaCode));
                        parent.set(province.get());
                    } else {
                        if (Arrays.asList(110000, 120000, 310000, 500000).contains(province.get())) {
                            parent.set(province.get());
                        } else {
                            parent.set(city.get());
                        }
                    }
                    return new Area(Integer.parseInt(areaCode), parent.get(), areaName.text());
                }).collect(Collectors.toList());

        saveBatch(areaList);
    }

    @Override
    public List<AreaVo> list(Integer parent) {
        return lambdaQuery()
                .eq(Area::getParent, parent)
                .list()
                .stream().map(area -> {
                    AreaVo areaVo = new AreaVo();
                    BeanUtils.copyProperties(area, areaVo);
                    return areaVo;
                }).collect(Collectors.toList());
    }
}
